#ifndef _RULE_H_
#define _RULE_H_
#include "Predicate.h"
#include <list>
#include <map>

class Rule{
public:
	int ruleNum;
	Predicate head;
	std::list<Predicate> body;
	Rule(){}
	Rule(int num){
		ruleNum=num;
	}
	void createRule(Predicate h, std::list<Predicate> b){
		head =h;
		body =b;
	}

	std::string toString(){
		std::string info;
		info = head.toString();
		info+= "<---";
		std::list<Predicate>::iterator begin=body.begin();
		std::list<Predicate>::iterator end = body.end();
		for(std::list<Predicate>::iterator i= begin ;i!=end;i++){
			info += i->toString();
			info += " ";
		}
		return info;
	}

	//如果rule符合规则，则返回规则编号，否则返回－1
	int match(Predicate p){
		if(p.predicateName.compare(head.predicateName))
			return -1;
		if(p.arguments != head.arguments)
			return -1;
		if(head.arguments==3){
			if( (head.argument1.getType()!=RDFS_VARIABLE) &&  head.argument1.getName().compare(p.argument1.getName()) ||
					(head.argument2.getType()!=RDFS_VARIABLE) &&  head.argument2.getName().compare(p.argument2.getName()) ||
					(head.argument3.getType()!=RDFS_VARIABLE) &&  head.argument3.getName().compare(p.argument3.getName())){
				return -1;
			}
		}else if(head.arguments==2){
			if( (head.argument1.getType()!=RDFS_VARIABLE) &&  head.argument1.getName().compare(p.argument1.getName()) ||
								(head.argument2.getType()!=RDFS_VARIABLE) &&  head.argument2.getName().compare(p.argument2.getName())){
				return -1;
			}
		}
		return ruleNum;
	}

	std::list<std::string> getVariablesNames(){
		std::list<std::string> vars;
		//check head
		vars = this->head.getVariablesNames();

		//check body
		std::list<Predicate>::iterator begin=this->body.begin();
		std::list<Predicate>::iterator end = this->body.end();
		for(std::list<Predicate>::iterator i=begin; i!=end;i++){
			std::list<std::string> s=i->getVariablesNames();
			std::list<std::string>::iterator s_beg=s.begin();
			std::list<std::string>::iterator s_end=s.end();
			for(std::list<std::string>::iterator it=s_beg;it!=s_end;it++){
				vars.push_back(*it);
			}
		}
		return vars;
	}

	Rule renameVariable(int num,int recursion){
		Rule renamedRule(num);
		Predicate h;
		if(this->head.arguments==2){
			h.predicateName=this->head.predicateName;
			h.argument1 = this->head.argument1;
			h.argument2 = this->head.argument2;
			h.arguments =2;
		}else if(this->head.arguments==3){
			h.predicateName=this->head.predicateName;
			h.argument1= this->head.argument1;
			h.argument2= this->head.argument2;
			h.argument3= this->head.argument3;
			h.arguments = 3;
		}
		h=h.renamePredicateVars(recursion);

		std::list<Predicate> b;
		std::list<Predicate>::iterator begin=this->body.begin();
		std::list<Predicate>::iterator end = this->body.end();
		for(std::list<Predicate>::iterator i=begin;i!=end;i++){
			Predicate p=*i;
			p=p.renamePredicateVars(recursion);
			b.push_back(p);
		}
		renamedRule.createRule(h,b);
		return renamedRule;
	}

	Predicate getHead(int ruleNum){
		return head;
	}
	std::list<Predicate> getBody(int ruleNum){
		return body;
	}

	std::map<std::string, Term> getSubstitution(Predicate p){
		std::map<std::string, Term> null_map;
		Term term("null");
		null_map["null"]=term;
		if (this->match(p)==-1) return null_map;
		std::map<std::string, Term> substitution;
		if(head.argument1.getType()==RDFS_VARIABLE)
			substitution.insert(std::map<std::string,Term>::value_type(head.argument1.getName(),p.argument1));
		if(head.argument2.getType()==RDFS_VARIABLE)
				substitution.insert(std::map<std::string,Term>::value_type(head.argument2.getName(),p.argument2));
		if(head.argument3.getName()!="Null" && head.argument3.getType()==RDFS_VARIABLE)
				substitution.insert(std::map<std::string,Term>::value_type(head.argument3.getName(),p.argument3));
		return substitution;
	}


};

#endif
